#include "StdAfx.h"
#include "TsVanillaEmpOptionPricer.h"
#include "vanillaempoption.h"
#include "OptionUtils.h"
#include "FdBlackScholesMertonHWVanillaEngine.h"
#include "blackScholesMertonHWProcess.h"

#include <exception>
#include <vector>

namespace TreasAlgo
{

TsVanillaEmpOptionPricer::TsVanillaEmpOptionPricer()
{
}


TsVanillaEmpOptionPricer::~TsVanillaEmpOptionPricer()
{
}

void TsVanillaEmpOptionPricer::priceOption(
	Date		valueDate,
	Date		maturity,
	Date		vestStartDate,
	Real		underlying,
	Real		strike,
	Rate		riskFreeRate,
	Spread		dividendYield,
	Real		empLossRate,
	Volatility	volatility,
	double		&NPV,
	double		&delta,
	double		&gamma,
	double		&theta)
{
	// Hard-coded values for now
	Calendar calendar = TARGET();
	DayCounter dayCounter = Actual365Fixed();
	Option::Type type(Option::Call);
	Date settlementDate = valueDate;

	// Exercise type
    Handle<Quote> underlyingH(
        boost::shared_ptr<Quote>(new SimpleQuote(underlying)));

    // bootstrap the yield/dividend/vol curves
	// Flat yield structure
    Handle<YieldTermStructure> flatTermStructure(
        boost::shared_ptr<YieldTermStructure>(
            new FlatForward(settlementDate, riskFreeRate, dayCounter)));

	// Flat dividend
    Handle<YieldTermStructure> flatDividendTS(
        boost::shared_ptr<YieldTermStructure>(
            new FlatForward(settlementDate, dividendYield, dayCounter)));

	// Flat employee loss rate
    Handle<YieldTermStructure> flatEmpLossTS(
        boost::shared_ptr<YieldTermStructure>(
            new FlatForward(settlementDate, empLossRate, dayCounter)));

	// Flat vol
    Handle<BlackVolTermStructure> flatVolTS(
        boost::shared_ptr<BlackVolTermStructure>(
            new BlackConstantVol(settlementDate, calendar, volatility, dayCounter)));

    boost::shared_ptr<StrikedTypePayoff> payoff(
                                    new PlainVanillaPayoff(type, strike));
	
	// BSM process for Employee stock options using Hull-White suggestion
	boost::shared_ptr<BlackScholesMertonHWProcess> bsmHWProcess(
				new BlackScholesMertonHWProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS, flatEmpLossTS));

    boost::shared_ptr<Exercise> americanExercise(
                                        new AmericanExercise(vestStartDate,
                                                             maturity));

	VanillaEmpOption empOption(vestStartDate, payoff, americanExercise);
    
	Size timeSteps = TsOptionUtils::getNumTimeSteps(valueDate, maturity);

	empOption.setPricingEngine(boost::shared_ptr<PricingEngine>(new FdBlackScholesMertonHWVanillaEngine(bsmHWProcess, 
																										timeSteps, 
																										timeSteps - 1)));
				
	NPV = empOption.NPV();
	delta = empOption.delta();
	gamma = empOption.gamma();
	theta = empOption.theta();
}

}
